package cn.buulog.camera;


import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.ImageReader;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.util.Arrays;

import cn.buulog.camera.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
    // 用于 Log
    private static final String TAG = "D_CAM";

    // Layout 绑定对象 代替 R.layout
    ActivityMainBinding thisBind;

    // 预览 View
    private TextureView mTextureView;

    private Button mControlLayout;


    // 当前CameraID
    private String mCameraId;

    // 相机设备
    private CameraDevice mCameraDevice;

    // 相机会话
    private CameraCaptureSession mCaptureSession;

    // 处理静态图像捕获的对象
    private ImageReader mImageReader;

    // 预览size
//    private Size mPreviewSize;

    // 运行时不阻塞 UI的附加线程
    private HandlerThread mBackgroundThread;

    // 用于在后台运行的Handle
    private Handler mBackgroundHandler;

    private CaptureRequest.Builder mPreviewRequestBuilder;

    private CaptureRequest mPreviewRequest;

    // 相机状态 预览
    private static final int STATE_PREVIEW = 0;
    //等待焦点锁定
    private static final int STATE_WAITING_LOCK = 1;
    //     等待曝光进入预览
    private static final int STATE_WAITING_PRECAPTURE = 2;
    //     Camera state: Waiting for the exposure state to be something other than precapture.
    private static final int STATE_WAITING_NON_PRECAPTURE = 3;
    //     Camera state: Picture was taken.
    private static final int STATE_PICTURE_TAKEN = 4;

    // AE参数
    private int mState = 0;


    private final CameraDevice.StateCallback mDeviceStateCb = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {
            // 相机打开时, 使用此方法
            mCameraDevice = cameraDevice;

            SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
            surfaceTexture.setDefaultBufferSize(1080, 1440);

            Surface surface = new Surface(surfaceTexture);

            // We set up a CaptureRequest.Builder with the output Surface.
            try {
                mPreviewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

                mPreviewRequestBuilder.addTarget(surface);

                cameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {

                    @Override
                    public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                        // The camera is already closed
                        if (null == cameraDevice) {
                            return;
                        }
                        try {
                            mCaptureSession = cameraCaptureSession;
                            // 预览需要设置对焦参数
                            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
                                    CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                            // Build实际的CaptureRequest

                            mPreviewRequest = mPreviewRequestBuilder.build();

                            // 重复绘画, 将预览数据填充到 Surface 中, 并且不需要CaptureRequest的返回参数
                            mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler);
                        } catch (CameraAccessException e) {
                            throw new RuntimeException(e);
                        }
                    }

                    @Override
                    public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                        Utils.showToast("Failed", getParent());
                    }
                }, null);
            } catch (CameraAccessException e) {
                throw new RuntimeException(e);
            }

        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
            // 相机断开使用此方法
            cameraDevice.close();
            mCameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int error) {
            // 相机错误
            cameraDevice.close();
            mCameraDevice = null;
            Activity activity = getParent();
            if (null != activity) {
                activity.finish();
            }
        }
    };

    private void openCamera(int width, int height) throws CameraAccessException {
        Log.i(TAG, "ddwb openCamera size" + width + height);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.CAMERA},
                    100
            );
//            shouldShowRequestPermissionRationale(Manifest.permission.CAMERA);
//            return;
        }

        // 设置预览参数
        Activity activity = this; // 从Activity获取服务, 不清楚为什么要这么做
        CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
        for (String cameraId : manager.getCameraIdList()) {
            Log.e(TAG, "ddwb cameraId:" + cameraId);
        }

        // 遍历可用 cameraId
        for (String cameraId : manager.getCameraIdList()) {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);

            // 获取前后摄
            Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
            if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) {
                continue;
            }
            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            if (map == null) {
                continue;
            }

            mCameraId = cameraId;
            break;
        }

        manager.openCamera(mCameraId, mDeviceStateCb, mBackgroundHandler);
    }

    // 拍照回调对象？
    private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {

        private void process(CaptureResult result) {
            switch (mState) {
                case STATE_PREVIEW: {
                    // We have nothing to do when the camera preview is working normally.
                    break;
                }
                case STATE_WAITING_LOCK: {
                    Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
                    if (afState == null) {
                        Log.e(TAG, "null: " + afState);

//                        captureStillPicture();
                    } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                            CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                        Log.e(TAG, "else: " + afState);
                        // CONTROL_AE_STATE can be null on some devices
                        Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                        if (aeState == null ||
                                aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                            mState = STATE_PICTURE_TAKEN;
//                            captureStillPicture();
                        } else {
//                            runPrecaptureSequence();
                        }
                    }
                    break;
                }
            }
        }

        @Override
        public void onCaptureProgressed(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull CaptureResult partialResult) {
            process(partialResult);
        }

        @Override
        public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
            process(result);
        }

    };

    private final View.OnClickListener mTakePictureControlListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 点击拍照按钮, 开始拍照
            Log.e(TAG, "ddwb start takephoto");

            // This is how to tell the camera to lock focus.
            mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                    CameraMetadata.CONTROL_AF_TRIGGER_START);
            // Tell #mCaptureCallback to wait for the lock.
            mState = STATE_WAITING_LOCK;
            try {
                mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                        mBackgroundHandler);
            } catch (CameraAccessException e) {
                throw new RuntimeException(e);
            }
        }
    };
    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
            = new ImageReader.OnImageAvailableListener() {

        @Override
        public void onImageAvailable(ImageReader reader) {
//            mBackgroundHandler.post(new Camera2BasicFragment.ImageSaver(reader.acquireNextImage(), mFile));
        }

    };

    // 创建 Surface监听,
    private final TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {

        @Override
        public void onSurfaceTextureAvailable(@NonNull SurfaceTexture texture, int width, int height) {
            Log.e(TAG, "Surface Size(" + width + "x" + height + ")");
            try {
                openCamera(width, height);
            } catch (CameraAccessException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture texture, int width, int height) {
//            configureTransform(width, height);
        }

        @Override
        public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture texture) {
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(@NonNull SurfaceTexture texture) {
        }
    };

    // 主界面创建函数，一般是入口
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBackgroundThread = new HandlerThread("CameraBackground");
        mBackgroundThread.start();
        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());

        mImageReader = ImageReader.newInstance(1080, 1440,
                ImageFormat.JPEG, /*maxImages*/2);
        mImageReader.setOnImageAvailableListener(
                mOnImageAvailableListener, mBackgroundHandler);

        //activity_camera
        thisBind = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(thisBind.getRoot());

        mTextureView = thisBind.textureCenter;
        mControlLayout = thisBind.takebutton;

        mControlLayout.setOnClickListener(mTakePictureControlListener);

        Log.e(TAG, "ddwb " + mTextureView.isAvailable());
        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
    }
}
